package org.colswe.testingProject.dao;

import java.util.ArrayList;
import java.util.Collection;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Query;
import org.colswe.testingProject.entity.Application;

/**
 *
 * @author andres
 */
public class ApplicationDao {

    /**
     * EntityManagerGactory necesario para crear EntityManager para las
     * operaciones en la base de datos.
     */
    private EntityManagerFactory emf;

    /**
     * Constructor de ApplicationDao.
     *
     * @param emf EntityManagerFactory necesario para cerar EntityManager.
     */
    public ApplicationDao(EntityManagerFactory emf) {
        this.emf = emf;
    }

    /**
     * Crear una Application.
     *
     * @param toCreate Application a crear.
     * @return Verdadero si se creó correctamente.
     */
    public boolean create(Application toCreate) {
        boolean result = true;
        EntityManager em = emf.createEntityManager();
        try {
            em.getTransaction().begin();
            em.persist(toCreate);
            em.getTransaction().commit();
        } catch (Exception ex) {
            result = false;
            System.err.println(ex.getMessage());
            ex.printStackTrace(System.err);
        } finally {
            if (em != null) {
                em.close();
            }
        }
        return result;
    }

    /**
     * Método para leer una Application.
     *
     * @param toRead Application a leer.
     * @return Application leída.
     */
    public Application read(Application toRead) {
        EntityManager em = emf.createEntityManager();
        Application application;
        try {
            Query query = em.createQuery("SELECT u FROM Application AS u "
                    + "WHERE u.id= :idParam");
            query.setParameter("idParam", toRead.getId());
            em.getTransaction().begin();
            application = (Application) query.getSingleResult();
            em.getTransaction().commit();
        } catch (Exception ex) {
            System.err.println(ex.getMessage());
            ex.printStackTrace(System.err);
            application = null;
        } finally {
            if (em != null && em.isOpen()) {
                em.close();
            }
        }
        return application;
    }

    /**
     * Método para leer todas las Application.
     *
     * @return Lista con todas las Application.
     */
    public Collection<Application> readAll() {
        Collection<Application> result = null;
        EntityManager em = emf.createEntityManager();
        try {
            Query query = em.createQuery("SELECT u FROM Application AS u");
            em.getTransaction().begin();
            result = query.getResultList();
            em.getTransaction().commit();
        } catch (Exception ex) {
            System.err.println(ex.getMessage());
            ex.printStackTrace(System.err);
            result = null;
        } finally {
            if (em != null) {
                em.close();
            }
        }
        return result;
    }

    /**
     * Método para filtrar las Application.
     *
     * @param filters Filtros para Application.
     * @return Lista de Application filtradas.
     */
    public Collection<Application> readByFilters(ArrayList<String> filters) {
        Collection<Application> result = null;
        String queryText = "SELECT u FROM Application AS u";
        int i = 0;
        if (filters.size() > 0) {
            queryText += " WHERE " + filters.get(i);
            for (i = 1; i < filters.size(); i++) {
                queryText += " AND " + filters.get(i);
            }
        }
        EntityManager em = emf.createEntityManager();
        try {
            Query query = em.createQuery(queryText);
            em.getTransaction().begin();
            result = query.getResultList();
            em.getTransaction().commit();
        } catch (Exception ex) {
            System.err.println(ex.getMessage());
            ex.printStackTrace(System.err);
            result = null;
        } finally {
            if (em != null) {
                em.close();
            }
        }
        return result;
    }

    /**
     * Método para actualizar Application.
     *
     * @param toUpdate Application a actualizar.
     * @return Verdadero si fue correcto.
     */
    public boolean update(Application toUpdate) {
        boolean result = true;
        EntityManager em = emf.createEntityManager();
        Application old;
        try {
            old = read(toUpdate);
            if (old != null) {
                toUpdate.setId(old.getId());
                em.getTransaction().begin();
                em.merge(toUpdate);
                em.getTransaction().commit();
            } else {
                throw new Exception("The registry does not exist");
            }
        } catch (Exception ex) {
            System.err.println(ex.getMessage());
            ex.printStackTrace(System.err);
            if (em.isOpen()) {
                em.getTransaction().rollback();
            }
            result = false;
        } finally {
            if (em != null && em.isOpen()) {
                em.close();
            }
        }
        return result;
    }

    /**
     * Método para eliminar una solicitud.
     *
     * @param toDelete Solicitud a eliminar.
     * @return Verdadero si es correcto.
     */
    public boolean delete(Application toDelete) {
        boolean result = true;
        EntityManager em = emf.createEntityManager();
        try {
            toDelete = read(toDelete);
            if (toDelete != null) {
                em.getTransaction().begin();
                toDelete = em.getReference(Application.class, toDelete.getId());
                em.remove(toDelete);
                em.getTransaction().commit();
            } else {
                throw new Exception("The registry does not exist");
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
            ex.printStackTrace(System.err);
            result = false;
        } finally {
            if (em != null) {
                em.close();
            }
        }
        return result;
    }
}
